import java.util.Arrays;

import static java.util.Arrays.parallelSort;

/**
 * 数组的定义与使用
 * 1.数组：相同类型元素的一个集合，在内存中是一段连续的空间，每个空间都有自己的下标，起始下标的编号为0，
 * 2.数组的创建
 * T[] 数组名 = new T[N]
 * T:表示数组中存放元素的类型
 * T[]：表示数组的类型
 * N：表示数组的长度
 */
public class Test {
//   int[] array1 = new int[10]; //创造一个可以容纳10个int类型元素的数组
//   double[] array2 = new double[5];//创造一个可以容纳5个double类型元素的数组
//   String[] array3 = new String[3];//创造一个可以容纳3个字符串元素的数组

    //数组的初始化
    //1.动态初始化：在创建数组的时候，直接指定数组中元素的个数
    //2.静态初始化：在创建数组时不直接指定元素个数，而直接将具体的数据内容进行指定
    //语法格式： T[] 数组名称 = {data1, data2, data3};
//    int[] array1 = new int[]{0, 1, 2, 3,};
//    double[] array2 = new double[]{1.0, 2.0, 3.0};
//    String[] array3 = new String[]{"hello", "world"};
    //注意：
    //1.静态初始化虽然没有指定数组的长度，但编译器会在编译的时候根据{}中的元素个数来确定数组的长度
    //2.静态初始化的时候，{}中的数据类型，必须和[]前面的类型保持一致
    //3.静态初始化可以省略后面的new T[]
//    double[] array = {2.0, 3.0};
//    int[] array1 = {1,2,3};
//    String[] arrary2 = {"hello", "world"};
    //虽然省去了new T[]，但是编译器在编译代码的时候还是会还原

    //静态和动态创建数组可以分为两步
//    public static void main(String[] args) {
//        int[] array1;
//        array1 = new int[10];
//
//        double[] array2;
//        array2 = new double[]{1.0,2.0};
//
//        //但省略的格式不可以拆分
//        int[] array3;
//        array3 = {1, 2, 3};//err
//    }

    //如果没有对数组进行初始化，则数组中的元素是有默认值的
    //基本类型大部分对应的都是0
    //boolean类型的默认值是false
    //引用类型的默认值是null
//    public static void main(String[] args) {
//        System.out.println();
//        boolean[] flgs = new boolean[3];
//        flgs[0] = true;
//    }

    //数组的使用
    //数组在内存中是一段连续的空间，空间的编号是从0开始的，依次递增
//    public static void main(String[] args) {
//        int[] arr = new int[]{10,20,30,40,50};
//        System.out.println(arr[0]);
//        System.out.println(arr[1]);
//        System.out.println(arr[2]);
//        System.out.println(arr[3]);
//        System.out.println(arr[4]);
//
//        arr[0] = 100;
//
//        System.out.println(arr[0]);
//    }
    //

//    public static void main(String[] args) {
//        int[] arr = new int[]{1,2,3};
//        System.out.println(arr[3]);
    //.ArrayIndexOutOfBoundsException表示数组越界访问
//    }

    //在数组中可以通过数组对象.length来获取数组的长度
//    public static void main(String[] args) {
//        int[] arr = new int[]{10,20,30,40,50};
//        for (int i = 0; i < arr.length; i++) {
//            System.out.println(arr[i]);
//        }
//    }

    //也可以使用for-each来遍历数组
//    public static void main(String[] args) {
//        int[] arr = new int[]{10, 20, 30, 40, 50};
//        for (int x:arr) {//int x:表示数组的类型 :后面表示数组名 for-each是遍历数组每一个元素，但注意没有拿到每一个数组元素的下标
//            System.out.println(x);
//        }
//    }


    //初始JVM的内存分布
    //虚拟机栈就是平时所说的栈，包含一些局部变量，返回地址等数据
    //堆：存储new创建的对象

    //基本数据类型创建的变量，该变量空间中直接存放的是其对应的值
    //而引用数据类型创建的变量，一般称为对象的引用，其空间中存储的是对象所在空间的地址
    //int[] array = new int[]{1,2,3}
    //array这个 引用 指向了 数组的 对象
    //          --- ----         ----

//    public static void fun1(int[] array) {
//        array = new int[10];
//    }
//
//    public static void fun2(int[] array) {
//        array[0] = 99;
//    }
//    public static void main(String[] args) {
//        int[] array = new int[]{1, 2, 3};
//        fun1(array);
//        for (int i = 0; i < array.length; i++){
//            System.out.print(array[i] + " "); //1 2 3
//        }
//
//        System.out.println();
//
//        fun2(array);
//        System.out.println(array[0]);
//    }

    //null的作用相当于C语言中的NULL（空指针），表示一个无效的内存位置，不能对这个内存位置进行任何的读写
    //java中并没有约定null和0号地址的内存有任何关联

    //Java中，数组这种引用变量可以作为函数的返回值
//    public static int[] fun(){
//        int[] ret = new int[]{1,2,3,4};
//        return ret;
//    }
//
//    public static void main(String[] args) {
//        int[] ret = fun();
//        String s = Arrays.toString(ret);// == >>
//        System.out.println(s);//           == >>
//        System.out.println(Arrays.toString(ret));
//        //Arrays.toString(ret).sout + 回车
//    }

    //或缺斐波那契数列的前N项
//    public static int[] fib(int n){
//        if (n <= 0){
//            return null;
//        }
//        int[] array = new int[n];
//        array[0] = array[1] = 1;
//        for (int i = 2; i < n; i++){ //注意这里的条件是 i < n 是因为 创建数组的时候 大小就是 n，下标是 0 ~ n-1
//            array[i] = array[i - 1] + array[i - 2];
//        }
//        return array;
//    }
//
//    public static void main(String[] args) {
//        int[] array = fib(10);
//        System.out.println(Arrays.toString(array));
//    }
    //java中提供了 java.util.Arrays这个包，包含了一些操作数组的常用方法
    //toString 是把数组的参数转化成了字符串输出

    //自我实现以下toString
//    public static String myToString1(int[] arr) {
//        String ret = "[";
//        for (int i = 0; i < arr.length - 1; i++) {
//
//            ret += arr[i];
//            ret += ", ";
//        }
//        ret += arr[arr.length - 1];
//        ret += "]";
//        return ret;
//    }
//
//    public static String myToString2(int[] arr) {
//        String ret = "[";
//        for (int i = 0; i < arr.length; i++) {
//
//            ret += arr[i];
//            if (i != arr.length - 1) {
//                ret += ", ";
//            }
//        }
//        ret += "]";
//        return ret;
//    }
//
//    public static void main(String[] args) {
//        int[] arr = new int[]{1, 2, 3, 4, 5};
//        String s = myToString2(arr);
//        System.out.println(s);
//    }

    //数组拷贝
//   public static int[] copyOf(int[] arr){
//       int[] ret = new int[arr.length];
//       for (int i = 0; i < arr.length; i++){
//           ret[i] = arr[i];
//       }
//       return ret;
//   }
//    public static void main(String[] args) {
//        int[] arr = new int[]{1,2,3,4,5};
//        int[] ret = copyOf(arr);
//        System.out.println(Arrays.toString(ret));
//
//    }

    //使用Arrays中copyOf方法完成数组的拷贝
    //copyOf方法在进行数组拷贝时，创建了一个新的数组
//    public static void main(String[] args) {
//        int[] array = new int[]{1,2,3,4,5,6};
//
//        int[] copy = Arrays.copyOf(array,array.length);
//
//        System.out.println(Arrays.toString(copy));
//    }

    //Arrays中的copyOf有很多重载的方法
//    public static void main(String[] args) {
//        int[] array = new int[]{1,2,3};
//        //此时就相当于扩容了，且扩大了的空间默认初始化为了0
//        int[] copy = Arrays.copyOf(array, array.length * 2);
//
//        System.out.println(Arrays.toString(copy));

    //Arrays中的copyOf中还可以指定复制
//    public static void main(String[] args) {
//        int[] array = new int[]{1, 2, 3, 4, 5, 6, 7};
//        int[] copy = Arrays.copyOfRange(array, 3, 6);
//        //注意 java中的Range一般都是左闭右开
//        System.out.println(Arrays.toString(copy));
//
//    }

//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] copy = new int[array.length];
//        System.arraycopy(array, 0, copy,0, array.length);
//        //public static native void arraycopy(Object src(源数组),  int  srcPos(数组开始拷贝的位置),
//        //                                        Object dest(目的数组), int destPos(目的数组的开始位置),
//        //                                        int length(拷贝的长度));
//        System.out.println(Arrays.toString(copy));
//    }

    //练习：求数组中元素的平均值
//    public static double avg(int[] array){
//        int sum = 0;
//        for (int x: array) {
//            sum += x;
//        }
//        return (double)sum / (double)array.length;
//    }
//
//    public static void main(String[] args) {
//        int[] array = new int[]{1,2,3,4,5};
//        double ret = avg(array);
//        System.out.println(ret);
//
//    }

    //给定一个数组，再给定一个元素，查找该元素在数组中的位置
//    public static int findIndexOfNum(int[] arr, int n){
//        for (int i = 0; i < arr.length; i++) {
//            if (n == arr[i]){
//                return i;
//            }
//        }
//        return -1;
//    }
//    public static void main(String[] args){
//        int[] array = new int[]{1,2,3,4,5,6,7};
//        System.out.println(findIndexOfNum(array, 6));
//    }

    //二分查找 - 针对有序数组
//    public static int binarySearch(int[] arr, int toFind){
//        int left = 0;
//        int right = arr.length - 1;
//        while(left <= right){
//            int mid = (right + left) / 2;
//            if (toFind > arr[mid]){
//                //要查找的数据在右半边
//                left = mid + 1;
//            }else if (toFind < arr[mid]){
//                //要查找的数据在左半边
//                right = mid - 1;
//            }else{
//                return mid;
//            }
//        }
//        return -1;//没有找到
//    }
//
//    public static void main(String[] args) {
//        int[] array = new int[]{1,2,3,4,5,6,7,8,9};
//        System.out.println(binarySearch(array, 5));
//    }

    //冒泡排序
    public static void bubbleSort1(int[] arr) {
        //i代表的是堂叔
        for (int i = 0; i < arr.length - 1; i++) {
            //j代表的是每一趟需要比较的次数
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    //对冒泡排序进行优化
//    public static void bubbleSort2(int[] arr){
//        //i代表的是堂叔
//        for (int i = 0; i < arr.length - 1; i ++){
//            boolean flg = false;
//            //j代表的是每一趟需要比较的次数
//            for (int j = 0; j < arr.length - 1 - i; j++){
//                if(arr[j] > arr[j + 1]){
//                    int temp = arr[j];
//                    arr[j] = arr[j + 1];
//                    arr[j + 1] = temp;
//                    flg = true;
//                }
//            }
//            if (flg == false){
//                break;//说明有序了
//            }
//        }
//    }
//
//    public static void main(String[] args) {
//        int[] arr = new int[]{6,8,2,6,731};
//        bubbleSort2(arr);
//        System.out.println(Arrays.toString(arr));
//    }

    //数组逆序
    //思路：设定两个下标，分别指向第一个元素和最后一个元素，交换两个位置的元素

//    public static void reverse(int[] arr){
//        int left = 0;
//        int right = arr.length - 1;
//        while (left < right) {
//            int temp = arr[left];
//            arr[left] = arr[right];
//            arr[right] = temp;
//
//            left++;
//            right--;
//        }
//    }
//
//    public static void main(String[] args) {
//        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
//        reverse(arr);
//        System.out.println(Arrays.toString(arr));
//
//    }

    //Java中提供的给数组排序
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,41,651,464,1616,};
//        Arrays.sort(array);
//        System.out.println(Arrays.toString(array));
//    }

    //Java中提供比较两个数组是否相同
//    public static void main(String[] args) {
//        int[] arr1 = new int[]{1, 2, 3, 4, 5};
//        int[] arr2 = new int[]{1, 2, 3, 4, 5};
//        int[] arr3 = new int[]{1, 2, 3, 4, 5, 6};
//        //比较两组的数字，对应位置，数据 是否相同
//        boolean flg1 = Arrays.equals(arr1,arr2);
//        System.out.println(flg1);
//        boolean flg2 = Arrays.equals(arr1,arr3);
//        System.out.println(flg2);
//
//    }

    //    public static void main(String[] args) {
//        int[] arr = new int[10];
//        Arrays.fill(arr, -1);
//        System.out.println(Arrays.toString(arr));
//        Arrays.fill(arr,1,3,9);//同样是左闭右开
//        System.out.println(Arrays.toString(arr));
//
//    }

    //按照数字顺序排序
//    public static void main(String[] args) {
//        int[] arr = {8, 5, 6, 7, 615, 21689, 56};
//        //按照数字顺序排序
//        parallelSort(arr);
//        System.out.println(Arrays.toString(arr));
//    }


}

